package com.xdf.whiteaccount.service.impl;

import java.util.*;

import com.xdf.whiteaccount.dao.AddressMapper;
import com.xdf.whiteaccount.dao.ContactCompanyMapper;
import com.xdf.whiteaccount.dao.CpBillfhMapper;
import com.xdf.whiteaccount.entity.Address;
import com.xdf.whiteaccount.entity.ContactCompany;
import com.xdf.whiteaccount.entity.CpBillfh;
import com.xdf.whiteaccount.entity.CpBillfhMain;
import com.xdf.whiteaccount.service.BillCodeService;
import com.xdf.whiteaccount.service.CpBillfhMainService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xdf.whiteaccount.dao.CpBillfhMainMapper;
import com.xdf.whiteaccount.utils.BusinessException;
import com.xdf.whiteaccount.utils.Example;

/**
 * 版本号：20240401
 * @Description : 服务层实现类，自定义代码写在最后，不要插在中间
 * @Author : chanchaw
 * @Date : 2025-4-14 11:00:43
 */
@Service
public class CpBillfhMainServiceImpl implements CpBillfhMainService {
    @Autowired
    private CpBillfhMainMapper dao;
    @Autowired
    private CpBillfhMapper cpBillfhMapper;
    @Autowired
    private BillCodeService billCodeService;
    @Autowired
    private ContactCompanyMapper contactCompanyMapper;
    @Autowired
    private AddressMapper addressMapper;

    @Override
    @Transactional
    public CpBillfhMain insert(CpBillfhMain record) {
        record = fullFill(record);
        doBeforeInsert(record);
        dao.insert(record);
        doAfterInsert(record);
        return record;
    }

    @Override
    @Transactional
    public CpBillfhMain insertSelective(CpBillfhMain record) {
        record = fullFill(record);
        doBeforeInsert(record);
        dao.insertSelective(record);
        doAfterInsert(record);
        return record;
    }

    /* 由于本方法无法返回所有对象的自增主键，后者调整为一个一个保存的方法
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiInsert(List<CpBillfhMain> list) {
        return dao.multiInsert(list);
    }
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<CpBillfhMain> multiInsert(List<CpBillfhMain> list) {
        list.forEach(item -> insertSelective(item));
        return list;
    }

    @Override
    public int updateByPrimaryKey(CpBillfhMain record) {
        checkSid4Update(record);
        return dao.updateByPrimaryKey(record);
    }

    @Override
    public int updateByPrimaryKeySelective(CpBillfhMain record) {
        checkSid4Update(record);
        return dao.updateByPrimaryKeySelective(record);
    }

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return dao.deleteByPrimaryKey(id);
    }

    @Override
    public CpBillfhMain selectByPrimaryKey(Integer id) {
        return dao.selectByPrimaryKey(id);
    }

    @Override
    public List<CpBillfhMain> selectAll(){
        return dao.selectAll();
    }

    @Override
    public CpBillfhMain save(CpBillfhMain record){
        if(record == null) throw new BusinessException("空对象不可保存！");
        Integer iid = Optional.ofNullable(record.getId()).orElse(0);
        if(iid.equals(0)) record = insertSelective(record);
        else updateByPrimaryKeySelective(record);
        return record;
    }

    // 没有使用 xml 中的 multiSave 方法是因为无法批量回写自增主键
    @Transactional
    @Override
    public List<CpBillfhMain> multiSave(List<CpBillfhMain> list){
        if(list == null || list.size()==0) return list;
        list.forEach(item -> item = save(item));
        return list;
    }

    /**=========================下面开始是固定模式代码=======================================*/

    // 新增前调用本方法将对象填充完整，然后调用 doBeforeInsert 再进行插入
    @Override
    public CpBillfhMain fullFill(CpBillfhMain record) {
        // TODO: 默认前端传递来的参数不需要填充完整，如果需要则使用自定义逻辑覆盖下面的代码
        return CpBillfhMainService.super.fullFill(record);
    }

    // 新增前调用的方法，抛出异常则不会新增数据
    @Override
    public void doBeforeInsert(CpBillfhMain record) {
        CpBillfhMainService.super.doBeforeInsert(record);
    }

    // 新增后调用的方法
    @Override
    public void doAfterInsert(CpBillfhMain record) {
        CpBillfhMainService.super.doAfterInsert(record);
    }

    // 是基础资料数据则修改之前要调用本方法
    // 检测修改后的目标 sid 是否已经存在
    // 这里要防止检测到自己 - 根据主键 iid 判断
    private void checkSid4Update(CpBillfhMain record){
        if(record == null) throw new BusinessException("传入了空对象，无法修改！");
        Integer iid = Optional.ofNullable(record.getId()).orElse(0);
        if(iid.equals(0)) throw new BusinessException("没有主键无法修改！");
        CpBillfhMain selectedRecord = selectByPrimaryKey(iid);
        if(selectedRecord == null) throw new BusinessException("主键" +iid+"的数据没有找到！");
    }

    @Override
    public List<CpBillfhMain> selectByExample(Example<CpBillfhMain> example){
        return dao.selectByExample(example);
    }
    //=================以上是自动生成的代码，自定义代码请写在下面==================

    /**
     * 新增发货单，并将细码单关联至发货单
     * @param cpBillfhMain
     * @param list
     * @return
     */
    @Override
    @Transactional
    public CpBillfhMain insertToFH(CpBillfhMain cpBillfhMain, List<CpBillfh> list) {
        if (list.size() == 0) throw new RuntimeException("未检测到任何数据！！");
        CpBillfh billfh = list.get(0);
        cpBillfhMain.setClient(billfh.getClient());
        if (cpBillfhMain.getDatafh() == null) cpBillfhMain.setDatafh(new Date());
        else cpBillfhMain.setDatafh(cpBillfhMain.getDatafh());
        cpBillfhMain.setBillcode(billCodeService.getNewBillCode("发货单"));
        dao.insertSelective(cpBillfhMain);
        for (CpBillfh cpBillfh : list) {
            if (!Optional.ofNullable(cpBillfh.getClient()).orElse("").equals(Optional.ofNullable(billfh.getClient()).orElse(""))) throw new BusinessException("所选细码单的客户必须一致！！");
            CpBillfh cpfh = cpBillfhMapper.selectByBillcode(cpBillfh.getBillcode());
            cpfh.setMainId(cpBillfhMain.getId());
            cpfh.setState(2);
            cpBillfhMapper.updateByPrimaryKeySelective(cpfh);
        }
        //将地址写入对应客户基础资料
        CpBillfhMain main = dao.selectByPrimaryKey(cpBillfhMain.getId());
        ContactCompany contactCompany = new ContactCompany();
        contactCompany.setCompanyName(cpBillfhMain.getClient());
        List<ContactCompany> contactCompanies = contactCompanyMapper.selectByParam(contactCompany);
        if (contactCompanies.size() > 0) {
            for (ContactCompany company : contactCompanies) {
                company.setAddress(cpBillfhMain.getAddress());
                contactCompanyMapper.updateByPrimaryKeySelective(company);
            }
        }
        //将地址写入地址表
        Address address = new Address();
        address.setParentId(contactCompany.getCompanyName());
        address.setLocation(cpBillfhMain.getAddress());
        List<Address> addresseList = addressMapper.selectByParam(address);
        if (addresseList.size() == 0) addressMapper.insertSelective(address);
        return main;
    }

    @Override
    @Transactional
    public int deleteFhd(Integer id) {
        List<CpBillfh> list = cpBillfhMapper.selectByMainId(id);
        if (list.size() > 0) {
            for (CpBillfh cpBillfh : list) {
                cpBillfh.setMainId(null);
                cpBillfh.setState(1);
                cpBillfhMapper.updateByPrimaryKey(cpBillfh);
            }
        }
        return dao.deleteByPrimaryKey(id);
    }

    /**
     * 修改
     * @param cpBillfhMain
     * @return
     */
    @Override
    public int update(CpBillfhMain cpBillfhMain) {
        int i = dao.updateByPrimaryKeySelective(cpBillfhMain);
        ContactCompany contactCompany = new ContactCompany();
        contactCompany.setCompanyName(cpBillfhMain.getClient());
        List<ContactCompany> contactCompanies = contactCompanyMapper.selectByParam(contactCompany);
        if (contactCompanies.size() > 0) {
            for (ContactCompany company : contactCompanies) {
                company.setAddress(cpBillfhMain.getAddress());
                contactCompanyMapper.updateByPrimaryKeySelective(company);
            }
        }
        //将地址写入地址表
        Address address = new Address();
        address.setParentId(contactCompany.getCompanyName());
        address.setLocation(cpBillfhMain.getAddress());
        List<Address> addresseList = addressMapper.selectByParam(address);
        if (addresseList.size() == 0) addressMapper.insertSelective(address);
        return i;
    }
}